<?php

/**
 * Impress - Open source digital signage
 *
 * @link http://digitalsignage.tk
 * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
 *
 * @category Impress
 * @package Impress
 */

/**
 * This class handles DataSource requests.
 *
 * @package Impress
 * @subpackage Controllers
 */

class ADS_DataSourceController extends ADS_DefaultController{

    const STATUS_ADD_OK    = 1;
    const STATUS_REMOVE_OK = 3;
    const STATUS_EDIT_OK   = 5;
    
    const ITEM_ADD_OK      = 1;
    const ITEM_REMOVE_OK   = 3;
    const ITEM_INCREASE_OK = 5;
    const ITEM_DECREASE_OK = 7;
    const ITEM_EDIT_OK     = 9;
    
    private static $sourceContent = array(
        'image' => 'Obrázky', 
        'video' => 'Video',
        'post'  => 'Příspěvky'
    );
    
    private static $sourceType = array(
        'item', 'tag'
    );
    
    const BULK_ACTION_REMOVE = 'remove';
    
    public function handleDefaultBulkAction(){
        //get variables 
        $post   =  (array)ADS_Input::postVar('post', array()); 
        $action = (string)_ifset(
            ADS_Input::postVar('action1', '-1') !== '-1',
            ADS_Input::postVar('action1', '-1'),
            ADS_Input::postVar('action2', '-1')
        );
        //validate token
        if(!wp_verify_nonce(ADS_Input::postVar('token', ''), $_GET['page'].':defaultBulkAction')){
            throw new ADS_VerifyTokenException('Token mismatch.');
        }
        //parse action
        switch ($action) {            
            case self::BULK_ACTION_REMOVE:                
                    $status = $this->bulkRemoveSources($post);                
                break;

            default:
                //action is not recognized (do nothing)
                //throw new ADS_UnknownBulkActionException('Action is not recognized.');
                break;
        }
        //redir
        ADS_Navigator::redir('self:defaultAction',array(
            'msg' => $status
        ));
    }
    
    public function handleItemBulkAction(){
        //get variables
        $post   =  (array)ADS_Input::postVar('post', array()); 
        $action = (string)_ifset(
            ADS_Input::postVar('action1', '-1') !== '-1',
            ADS_Input::postVar('action1', '-1'),
            ADS_Input::postVar('action2', '-1')
        );
        //validate token
        if(!wp_verify_nonce(ADS_Input::postVar('token', ''), $_GET['page'].':itemBulkAction')){
            throw new ADS_VerifyTokenException('Token mismatch.');
        }
        //parse action
        switch ($action) {            
            case self::BULK_ACTION_REMOVE:                
                    $status = $this->bulkRemoveItems($post);                
                break;

            default:
                //action is not recognized (do nothing)
                //throw new ADS_UnknownBulkActionException('Action is not recognized.');
                break;
        }
        //redir
        ADS_Navigator::redir('self:editItems',array(
            'msg' => $status
        ), 'sourceId');
    }
    
    public function bulkRemoveSources($sources){
        //validate parameters
        if(!is_array($sources)){
            throw new InvalidArgumentException(sprintf('Wrong parameters for method %s.',__METHOD__));
        }
        ADS_Navigator::freeze();        
        foreach ($sources as $sourceId) {
            $this->handleRemoveSource((int)$sourceId, false);
        }
        ADS_Navigator::unfreeze();        
    }
    
    public function bulkRemoveItems($items){
        //validate parameters
        if(!is_array($items)){
            throw new InvalidArgumentException(sprintf('Wrong parameters for method %s.',__METHOD__));
        }
        ADS_Navigator::freeze();
        foreach ($items as $itemId) {
            $this->handleRemoveItem((int)$itemId, false);
        }
        ADS_Navigator::unfreeze();        
    }
    
    public function handleRemoveSource($sourceId = 0, $useToken = true){
        //validate parameters
        if(!is_int($sourceId) || !is_bool($useToken)){
            throw new InvalidArgumentException(sprintf('Wrong parameters for method %s.',__METHOD__));
        }
        //validate token
        if($useToken && !wp_verify_nonce(ADS_Input::getVar('token', ''), $_GET['page'].':removeSource')){
            throw new ADS_VerifyTokenException('Token mismatch.');
        }
        //get variables
        $sourceId = (int)_ifset($sourceId > 0, $sourceId, ADS_Input::getVar('sourceId', 0));
        //remove source
        $dsModel = new ADS_DataSourceModel();
        $dsModel->removeSource($sourceId);
        //redir
        ADS_Navigator::redir('self:defaultAction',array(
            'msg' => self::STATUS_REMOVE_OK
        ));
    }
    
    public function handleRemoveItem($itemId = 0, $useToken = true){        
        //validate parameters
        if(!is_int($itemId) || !is_bool($useToken)){
            throw new InvalidArgumentException(sprintf('Wrong parameters for method %s.',__METHOD__));
        }
        //validate token
        if($useToken && !wp_verify_nonce(ADS_Input::getVar('token', ''), $_GET['page'].':removeItem')){
            throw new ADS_VerifyTokenException('Token mismatch.');
        }
        //get variables
        $itemId = (int)_ifset($itemId > 0, $itemId, ADS_Input::getVar('itemId', 0)); 
        //remove frame
        $dfiModel = new ADS_DataSourceItemModel();
        $dfiModel->removeItem($itemId);
        //redir
        ADS_Navigator::redir('self:editItems',array(
            'msg' => self::ITEM_REMOVE_OK
        ), 'sourceId');
    }
    
    public function handleAddSource(){
        
        $dsModel = new ADS_DataSourceModel();
        //default values
        $source      = array();        
        $isValid     = true;
        //resolve action
        $action = ADS_Input::postVar('action', 'default');         
        switch($action){
            case 'add':
                $source['name']    = (string)ADS_Input::postVar('source.name', '');
                $source['content'] = (string)ADS_Input::postVar('source.content', '');
                $source['type']    = (string)ADS_Input::getVar('source_type', 'item');
                //validation
                if(mb_strlen($source['name']) == 0){
                    ADS_MsgStack::push('error', sprintf('Name of source can not be blank.'));
                    $isValid = false;
                }                
                if(mb_strlen($source['name']) > 0 && (mb_strlen($source['name']) < 4 || mb_strlen($source['name']) > 255)){
                    ADS_MsgStack::push('error', sprintf('Name of source must be between %d and %d characters long.', 4, 255));
                    $isValid = false;
                }

                if(!in_array($source['content'], array_keys(self::$sourceContent))){
                    ADS_MsgStack::push('error', sprintf('Wrong value of source content.'));
                    $isValid = false;
                }
                if(!in_array($source['type'], self::$sourceType)){
                    ADS_MsgStack::push('error', sprintf('Wrong value of source type.'));
                    $isValid = false;
                }
                
                if($isValid){
                    //insert new source to db
                    $dsModel->addSource($source);
                    //redir
                    ADS_Navigator::redir('self:defaultAction',array(
                        'msg' => self::STATUS_ADD_OK
                    ));
                }                
                break;                
        }  
        //add variables to output
        ADS_Output::register('source', $source);
        ADS_Output::register('source_content', self::$sourceContent);
        ADS_Output::register('errors', $errors);
        
    }
    
    public function handleEditSource(){
        
        $dsModel = new ADS_DataSourceModel();
        //default values
        $sourceId = (int)ADS_Input::getVar('sourceId', 0);
        $source   = $dsModel->getSource($sourceId);
        $isValid = true;
        //resolve action
        $action = ADS_Input::postVar('action', 'default');         
        switch($action){
            case 'edit':
                $source = array();
                //get values
                $source['name'] = (string)ADS_Input::postVar('source.name', '');
                //validation
                if(mb_strlen($source['name']) == 0){
                    ADS_MsgStack::push('error', sprintf('Name of source can not be blank.'));
                    $isValid = false;
                }                
                if(mb_strlen($source['name']) > 0 && (mb_strlen($source['name']) < 4 || mb_strlen($source['name']) > 255)){
                    ADS_MsgStack::push('error', sprintf('Name of source must be between %d and %d characters long.', 4, 255));
                    $isValid = false;
                }
                //ready to go
                if($isValid){
                    //edit source in db
                    $dsModel->editSource($sourceId, $source);
                    //redir
                    ADS_Navigator::redir('self:defaultAction', array(
                        'msg' => self::STATUS_EDIT_OK
                    ));
                }                
                break;                
        }  
        //add variables to output
        ADS_Output::register('source', $source);
        ADS_Output::register('source_content', self::$sourceContent);
        ADS_Output::register('errors', $errors);
        
    } 
    
    public function handleEditItems(){
        
        //default values  
        $page     =    (int)ADS_Input::getVar('paged', 1);
        $orderBy  = (string)ADS_Input::getVar('orderBy', 'position');
        $order    = (string)ADS_Input::getVar('order', 'ASC');
        $sourceId =    (int)ADS_Input::getVar('sourceId', 0);
        $item     = array();      
        //prepare filter
        $status = (string)ADS_Input::getVar('status_valid', '-1');
        $filter = array(
            'now' => array(
                array('validFrom <= NOW()'),
                array('validTo >= NOW()')
            ),
            'future' => array(
                array('validFrom > NOW()')
            ),
            'past' => array(
                array('validTo < NOW()')
            ),
        );
        //load data source models
        $dsModel = new ADS_DataSourceModel();
        $wpModel = new ADS_WPModel();
        $dsiModel = null;
        //get source and its items
        $source   =  $dsModel->getSource($sourceId);
        $dsiModel = new ADS_DataSourceItemModel($source->content, $source->type);
        //resolve action
        $action = ADS_Input::postVar('action', 'default'); 
        //execute action
        switch ($action) {
            case 'add':
                $isValid = true;
                //values
                $item['sourceId']  = $sourceId;
                //get values
                $item['targetId']  =    (int)ADS_Input::postVar('item.targetId', -1);
                $item['validFrom'] = (string)ADS_Input::postVar('item.validFrom', '');
                $item['validTo']   = (string)ADS_Input::postVar('item.validTo', '');                
                $item['duration']  =    (int)ADS_Input::postVar('item.duration', 10);                
                //validate
                if(!ads_checkdate($item['validFrom']) || !ads_checkdate($item['validTo'])){
                    ADS_MsgStack::push('error', sprintf('Wrong format of date. Must be dd/mm/yyyy.'));
                    $isValid = false;
                }
                //ready to go
                if($isValid){
                    //insert new item to timeline
                    $dsiModel->addItem($item);
                    //redir
                    ADS_Navigator::redir('self:editItems',array(
                        'msg' => self::ITEM_ADD_OK                        
                    ), 'sourceId');
                }

                break;
        }
        //prepare sorting
        $rules = ads_prepare_sorting($orderBy, $order, array(
            'name', 'position', 'validFrom', 'validTo'
        ));
        //count records
        $cnt = (int)$dsiModel->setFilter((array)@$filter[$status])->countItems($sourceId);
        //output        
        ADS_Output::register(
            'source_items', 
            $dsiModel->setFilter((array)@$filter[$status])->setSorter($rules)->setPager($page)->getItems($sourceId)
        );
        ADS_Output::register(
            'pager',
            ads_prepare_paging($page, $dsiModel->getLimit(), $cnt)
        );
        ADS_Output::register('source', $source);
        ADS_Output::register('item', $item);
        switch($source->type){
            case 'item':
                $items = ads_prepare_options(
                    $wpModel->getPosts($source->content), 
                    'itemId', 
                    'name'
                );
                break;
            case 'tag':
                $items = ads_prepare_options(
                    $wpModel->getTags(), 
                    'tagId', 
                    'name'
                );
                break;
            default:
                throw new ADS_UnknownSourceException('Correct driver can not be loaded.');
        }
        ADS_Output::register('items', $items);
        ADS_Output::register(
            'cnt',
            array(
                'all'    => $dsiModel->setFilter(array())->countItems($sourceId),
                'now'    => $dsiModel->setFilter($filter['now'])->countItems($sourceId),
                'future' => $dsiModel->setFilter($filter['future'])->countItems($sourceId),
                'past'   => $dsiModel->setFilter($filter['past'])->countItems($sourceId)
            )            
        );
        //restore message
        $msg = (int)ADS_Input::getVar('msg', -1);
        if($msg === self::ITEM_ADD_OK){
            ADS_MsgStack::push('success', 'Item was successfully inserted.');
        }
        if($msg === self::ITEM_REMOVE_OK){
            ADS_MsgStack::push('success', 'Item was successfully removed.');
        }
        if($msg === self::ITEM_DECREASE_OK){
            ADS_MsgStack::push('success', 'Position was successfully changed.');
        }
        if($msg === self::ITEM_INCREASE_OK){            
            ADS_MsgStack::push('success', 'Position was successfully changed.');
        }
    }
    
    public function handleDefaultAction(){
        //get variables
        $page    =    (int)ADS_Input::getVar('paged', 1);
        $orderBy = (string)ADS_Input::getVar('orderBy', '');
        $order   = (string)ADS_Input::getVar('order', 'ASC');
        //prepare filter
        $status = (string)ADS_Input::getVar('status_content', '-1');
        $filter = array(
            'video' => array(
                array('content = %s', 'video')
            ),
            'image' => array(
                array('content = %s', 'image')
            ),
            'post' => array(
                array('content = %s', 'post')
            )
        );
        //prepare sorting
        $rules = ads_prepare_sorting($orderBy, $order, array(
            'name', 'content', 'type'
        ));
        //load sources
        $dsModel = new ADS_DataSourceModel();
        //count records
        $cnt = (int)$dsModel->setFilter((array)@$filter[$status])->countSources();
        ADS_Output::register(
            'sources',
            $dsModel->setFilter((array)@$filter[$status])->setSorter($rules)->setPager($page)->getSources()
        );
        ADS_Output::register(
            'pager',
            ads_prepare_paging($page, $dsModel->getLimit(), $cnt)
        );
        ADS_Output::register(
            'cnt',
            array(
                'all'   => $dsModel->setFilter(array())->countSources(),
                'image' => $dsModel->setFilter($filter['image'])->countSources(),
                'video' => $dsModel->setFilter($filter['video'])->countSources(),
                'post'  => $dsModel->setFilter($filter['post'])->countSources()
            )            
        );
        //restore message
        $msg = (int)ADS_Input::getVar('msg', -1);
        if($msg === self::STATUS_ADD_OK){
            ADS_MsgStack::push('success', 'Source was successfully inserted.');
        }
        if($msg === self::STATUS_EDIT_OK){
            ADS_MsgStack::push('success', 'Source was successfully updated.');
        }
        if($msg === self::STATUS_REMOVE_OK){
            ADS_MsgStack::push('success', 'Source was successfully removed.');
        }        
    }
    
    public function handleIncreaseItemPosition(){        
        //increase position
        $dsiModel = new ADS_DataSourceItemModel();
        $dsiModel->increaseItemPosition((int)ADS_Input::getVar('itemId', 0));
        //redir
        ADS_Navigator::redir('self:editItems',array(
            'msg' => self::ITEM_INCREASE_OK
        ), 'sourceId');
    }
    
    public function handleDecreaseItemPosition(){        
        //decrease position
        $dsiModel = new ADS_DataSourceItemModel();
        $dsiModel->decreaseItemPosition((int)ADS_Input::getVar('itemId', 0));
        //redir
        ADS_Navigator::redir('self:editItems',array(
            'msg' => self::ITEM_DECREASE_OK
        ), 'sourceId');
    } 
    
    public function handleEditItem(){ 
        //default values
        $itemId   = (int)ADS_Input::getVar('itemId', 0);
        $sourceId = (int)ADS_Input::getVar('sourceId', 0);
        //load sources
        $dsModel  = new ADS_DataSourceModel();        
        $source = $dsModel->getSource($sourceId);
        $dsiModel = new ADS_DataSourceItemModel($source->content,$source->type);
        $item   = $dsiModel->getItem($itemId);        
        $isValid = true;
        //resolve action
        $action = ADS_Input::postVar('action', 'default');         
        switch($action){
            case 'edit':
                $item = array();
                //get values
                $item['position']  =    (int)ADS_Input::postVar('item.position', -1);
                $item['duration']  =    (int)ADS_Input::postVar('item.duration', 10);
                $item['validFrom'] = (string)ADS_Input::postVar('item.validFrom', date('Y/m/d'));
                $item['validTo']   = (string)ADS_Input::postVar('item.validTo', date('Y/m/d'));   
                //validate
                if(!ads_checkdate($item['validFrom']) || !ads_checkdate($item['validTo'])){
                    ADS_MsgStack::push('error', sprintf('Wrong format of date. Must be dd/mm/yyyy.'));
                    $isValid = false;
                }
                //validation
                if($item['position'] === -1){
                    ADS_MsgStack::push('error', sprintf('Position can not be blank.'));
                    $isValid = false;
                }
                //ready to go
                if($isValid){
                    //insert new frame to db
                    $dsiModel->editItem($itemId, $item);
                    //redir
                    ADS_Navigator::redir('self:editItems',array(
                        'msg' => self::ITEM_EDIT_OK
                    ), 'sourceId');
                }                
                break;                
        }  
        //add variables to output
        ADS_Output::register('item', $item);
        ADS_Output::register('source', $source);
        ADS_Output::register('errors', $errors);
        
    }
    
}